#include "sys.h"
#include "log.h"
#include "pcap_output.h"
typedef struct {
    unsigned int second;
    unsigned int mili;
    unsigned int cap_length;
    unsigned int packet_length;
} Ether_Frame_Header;

// 20 bytes
static unsigned char pcap_file_header[] = {
    0xD4, 0xC3, 0xB2, 0xA1, 0x02, 0x00, 0x04, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0xFF, 0xFF, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
};

pcap_output_t* pcap_output_new(char* filename, int max_size, int count)
{
    pcap_output_t* pout = malloc(sizeof(pcap_output_t));
    if (!pout) {
        log_syserr("New pcap conf error.");
        return NULL;
    }
    memset(pout, 0, sizeof(pcap_output_t));
    pout->enable = 1;
    pout->sync = 0;
    pout->fp = fopen(filename, "wb");
    pout->file_max_size = max_size;
    pout->pkt_count = count;
    pcap_output_lock_init(pout);
    fwrite(pcap_file_header, 1, sizeof(pcap_file_header), pout->fp);
    return pout;
}
void pcap_set_sync(pcap_output_t* pout)
{
    pout->sync = 1;
}
void pcap_set_disable(pcap_output_t* pout)
{
    pout->enable = 0;
}
int pcap_output(pcap_output_t* pout, Packet_t* packet)
{
    int size = 0;
    struct timeval t_now;
    Ether_Frame_Header h;

    assert(pout != NULL);
    if (pout->enable == 0)
        return PCAP_OUTPUT_ERR_NONE;
        
    assert(packet != NULL);
    assert(pout->fp != NULL);


    pcap_output_lock(pout);
    if (pout->cur_size >= pout->file_max_size * 1024 && pout->file_max_size != 0) {
        fflush(pout->fp);
        pcap_output_unlock(pout);
        return PCAP_OUTPUT_ERR_MAX_SIZE;
    }
    if (pout->cur_count >= pout->pkt_count && pout->pkt_count != 0) {
        fflush(pout->fp);
        pcap_output_unlock(pout);
        return PCAP_OUTPUT_ERR_MAX_COUNT;
    }

    gettimeofday(&t_now, NULL);
    h.second = t_now.tv_sec;
    h.mili = t_now.tv_usec;
    h.cap_length = packet->len;
    h.packet_length = packet->len;

    size = fwrite(&h, 1, sizeof(h), pout->fp);
    size += fwrite(packet->buf, 1, packet->len, pout->fp);
    if (pout->sync)
        fflush(pout->fp);

    pout->cur_size += size;
    pout->cur_count++;
    pcap_output_unlock(pout);
    return PCAP_OUTPUT_ERR_NONE;
}
void pcap_output_finish(pcap_output_t* pout)
{
    assert(pout != NULL);
    assert(pout->fp != NULL);

    fclose(pout->fp);
    free(pout);
}
